package com.example.myapplication.base;


import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.databinding.DataBindingUtil;
import androidx.databinding.ViewDataBinding;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModel;
import androidx.lifecycle.ViewModelProvider;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;


public abstract class BaseFragment<V extends ViewDataBinding, VM extends BaseViewModel> extends UIFragment implements IBaseView {

    protected V dataBinding;
    protected VM viewModel;
    private int viewModelId;

    @Nullable
    private Map<String, Object> mArgs;

    public void setArgs(@Nullable Map<String, Object> args) {
        mArgs = args;
    }

    public void setArg(String key, Object value) {
        if (mArgs == null) {
            mArgs = new HashMap<>();
        }
        mArgs.put(key, value);
    }

    @Nullable
    public Map<String, ?> getArgs() {
        return mArgs;
    }

    @Nullable
    public Object getArg(String key) {
        return mArgs == null ? null : mArgs.get(key);
    }

    public void removeArg(String key) {
        if (mArgs != null) {
            mArgs.remove(key);
        }
    }

    public void clearArgs() {
        if (mArgs != null) {
            mArgs.clear();
        }
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initParam();
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        super.onCreateView(inflater, container, savedInstanceState);
        dataBinding = DataBindingUtil.inflate(inflater, initContentView(inflater, container, savedInstanceState), container, false);
        return dataBinding.getRoot();
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        // 私有的初始化Databinding和ViewModel方法
        initViewDataBinding();
        // 页面数据初始化方法
        initData();
        // 页面事件监听的方法，一般用于ViewModel层转到View层的事件注册
        initViewObservable();
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        if (dataBinding != null) {
            dataBinding.unbind();
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        clearArgs();
    }

    /**
     * 私有的初始化Databinding和ViewModel方法
     */
    private void initViewDataBinding() {
        viewModelId = initVariableId();
        viewModel = initViewModel();
        if (viewModel == null) {
            Class modelClass;
            Type type = getClass().getGenericSuperclass();
            if (type instanceof ParameterizedType) {
                modelClass = (Class) ((ParameterizedType) type).getActualTypeArguments()[1];
            } else {
                // 如果没有指定泛型参数，则默认使用BaseViewModel
                modelClass = BaseViewModel.class;
            }
            viewModel = (VM) createViewModel(this, modelClass);
        }
        // 关联ViewModel
        dataBinding.setVariable(viewModelId, viewModel);
        // 支持LiveData绑定xml，数据改变，UI自动更新
        dataBinding.setLifecycleOwner(this);
        // ViewModel绑定View的生命周期
        getLifecycle().addObserver(viewModel);
        // 注入Lifecycle生命周期
        viewModel.injectLifecycleProvider(this);
    }

    /**
     * 初始化根布局
     *
     * @return 布局layout的id
     */
    public abstract int initContentView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState);

    /**
     * 初始化ViewModel的id
     *
     * @return BR的id，举例：BR.viewModel
     */
    public abstract int initVariableId();

    /**
     * 初始化ViewModel
     *
     * @return 继承BaseViewModel的ViewModel
     */
    public VM initViewModel() {
        return viewModel;
    }

    @Override
    public void initParam() {

    }

    @Override
    public void initData() {

    }

    @Override
    public void initViewObservable() {

    }

    public <T extends ViewModel> T createViewModel(Fragment fragment, Class<T> cls) {
        return new ViewModelProvider(fragment).get(cls);
    }

    @Nullable
    @Override
    public Object getLogTag() {
        return this.getClass().getSimpleName();
    }
}
